package com.calms.study.config;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 监听服务是否启动成功
 */
@Slf4j
@Order
@Component
public class ApplicationEvenListener implements CommandLineRunner, ApplicationRunner, ApplicationListener<ApplicationEvent> {

    @Override
    public void run(String... args) {
        log.info("CommandLineRunner args:{}", JSONUtil.toJsonStr(args));
        RuntimeMXBean runtimeJvmBean = ManagementFactory.getRuntimeMXBean();
        long uptime = runtimeJvmBean.getUptime();
        String jvmStartTime = formatMillis(uptime);
        log.info("ApplicationEvenListener CommandLineRunner jvmStartTime: {}: ", jvmStartTime);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("ApplicationArguments args: {}", JSONUtil.toJsonStr(args));
    }

    /**
     * 监听到的SpringBoot事件
     * @param event 事件信息
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        log.info("Application event received: {}, eventData:{}", event, event.getSource());
        if (event instanceof ApplicationStartedEvent startedEvent) {
            log.info("应用启动耗时:{}", formatMillis(startedEvent.getTimeTaken().toMillis()));
        }
        if (event instanceof ApplicationReadyEvent readyEvent) {
            log.info("应用已完全启动，可以开始处理请求, 完全就绪耗时: {}", formatMillis(readyEvent.getTimeTaken().toMillis()));
            currentDatabaseLog();
        }
    }

    public void currentDatabaseLog() {
        SpringUtil.getBeansOfType(DataSource.class).forEach((k, v) -> {
            log.info("数据源名称->>{}----数据源信息->>{}", k, JSONUtil.toJsonStr(v));
        });
        DynamicRoutingDataSource routingDataSource = null;
        try {
            routingDataSource = SpringUtil.getBean(DynamicRoutingDataSource.class);
            final Map<String, DataSource> currentDataSources = routingDataSource.getDataSources();
            log.info("当前服务所拥有的的数据源信息->{}", JSONUtil.toJsonStr(currentDataSources.keySet()));
        } catch (Exception e) {
            log.error("获取数据源信息失败,", e);
        }
    }

    /**
     * 将毫秒转换为秒和分
     */
    public static String formatMillis(long milliseconds) {
        long minutes = TimeUnit.MILLISECONDS.toMinutes(milliseconds);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(milliseconds)
                - TimeUnit.MINUTES.toSeconds(minutes);
        return String.format("%d 分 %d 秒", minutes, seconds);
    }


}
